// -*- C++ -*-

//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2009-05-29 15:24
 */
//========================================================================

#ifndef NDK_OS_H_
#define NDK_OS_H_

#include "ndk/types.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

// Previous declare
#if defined NDK_LINUX
# include <fcntl.h>
# include <unistd.h>
# include <sys/uio.h>
# include <sys/socket.h>
# include <errno.h>
#elif defined NDK_WIN32
# include <io.h>
#endif

#if defined NDK_WIN32
// = For file stat
typedef struct _stat ndk_stat;
typedef int  mode_t;

enum
  {
    O_CREAT	  = 0x01,
    O_RDWR	  = 0x02,
    O_RDONLY	= 0x04,
    O_WRONLY	= 0x08,
    O_APPEND	= 0x10,
    O_TRUNC	  = 0x20,
    O_EXCL    = 0x40
  };
// = For the scatter/gather type of I/O
// The ordering of the fields in this struct is important.  It has to
// match those in WSABUF.
struct iovec
{
  // byte count to read/write
  u_long iov_len;

  // data to be read/written
  char *iov_base;

  operator WSABUF &(void) { return *((WSABUF *) this); }
};
#elif defined NDK_LINUX
  typedef struct stat ndk_stat;
#endif
/**
 * @class ndk_os
 *
 * @brief 
 */
namespace ndk_os
{
  using namespace ndk;

  inline extern int snprintf(char *buf, size_t maxlen, const char *format, ...);

  inline extern int vsnprintf(char *buf, size_t maxlen, 
                              const char *format, va_list ap);

  inline extern int last_error();

  inline extern void last_error(int err);

  inline extern ndk_handle socket(int domain, int type, int protocol);

  inline extern int closesocket(ndk_handle handle);

  inline extern int bind(ndk_handle handle,
                         struct sockaddr *addr,
                         int addrlen);

  inline extern int listen(ndk_handle handle,
                           int backlog);

  inline extern ndk_handle accept(ndk_handle listen_handle,
                                  struct sockaddr *addr,
                                  int *addrlen);

  inline extern int connect(ndk_handle handle,
                            const struct sockaddr *addr,
                            int addrlen);

  inline extern int recv(ndk_handle handle,
                         void *buff,
                         size_t len,
                         int flags);

  inline extern int recvfrom(ndk_handle handle,
                             void *buff,
                             size_t len,
                             int flags,
                             struct sockaddr *from, 
                             int *fromlen);

  inline extern int send(ndk_handle handle, 
                         const void *buff, 
                         size_t len, 
                         int flags); 

  inline extern int sendto(ndk_handle handle,
                           const void *buff,
                           size_t len,
                           int flags,
                           const struct sockaddr *to, 
                           int tolen);

  inline extern int readv(ndk_handle handle, 
                          iovec iov[], 
                          size_t count); 

  inline extern int writev(ndk_handle handle, 
                           const iovec iov[], 
                           size_t count); 

  inline extern int setsock_reuseaddr(ndk_handle handle,
                                      int val = 1);

  inline extern int setsock_rcvbuf(ndk_handle handle,
                                   size_t size);

  inline extern int setsock_sndbuf(ndk_handle handle,
                                   size_t size);

  inline extern int getsock_error(ndk_handle handle, 
                                  int &err);

  // = File System I/O
  inline extern int open(const char *filename,
                         int flags,
                         mode_t mode);

  inline extern int open(const char *filename,
                         int flags);

  inline extern int read(ndk_handle handle, 
                         void *buff, 
                         size_t len); 

  inline extern int write(ndk_handle handle, 
                          const void *buff, 
                          size_t len); 

  inline extern int close(ndk_handle handle);

  inline extern int stat(const char *name,
                         ndk_stat *st_buf);

  // If file is exist, return 1 else return 0.
  inline extern int exists(const char *filename);

  inline extern int mkdir(const char *name,
                          mode_t );

  inline extern int rename(const char *old_name,
                           const char *new_name);

  inline extern int unlink(const char *filename);
}

#include "ndk/ndk_os.inl"
#endif // NDK_OS_H_

